<?php
    /*
    *   D3Sql Class v1.1.16
    * ============================================================
    * Kodlayan: Tufan Barış YILDIRIM & Savaş YILDIRIM
    * Website : http://www.tufyta.com & www.savasyildirim.com
    * ===================Versiyon Notları=========================
    *  v1.1.16  Savaş
    * =========
    * -- sutun_template ve aktif_sutunlar  sql() fonksiyonunda boşaltıldı
    *  v1.1.15
    * ========  01.11.2009
    * -- Dizi Aktarımındaki Hata Gösterimi Kaldırıldı.
    *  v1.1.14
    * ========
    * -- Jump() özelliği eklendi. mysql_data_seek görevi görüyor.
    * -- Plugin_Yeri Fonksiyonunda Değişiklşik yapıldı (Plugin Önce var mı diye kontrol eklendi.)
    *  v1.1.13
    * ========
    * -- Plugin Desteği eklendi
    * -- plugin_ekle ile fonksiyonlarınızı dahil edebilrisiniz.
    * -- Birden Fazla Grid yapılabilmesi için Gridden sonra DataSource Free kodu kaldırıldı
    *  v1.1.12
    * ======== 07.10.2009
    * -- Gridi içine alan <div> kaldırıldı.
    * -- mysql dataseti boşaltmak için Free() Fonksiyonu eklendi.
    * -- template fonksiyonu  sütun dizisi kullaılınca sadece dizideki sütunları replace edecek şekilde ayarlandı
    *  v1.1.11
    * =======  03.10.2009 
    * -- Template Fonksiyonu için artık Dizi yazmak gerekmicek. bunun tüm sutunlar için {$sutun_adi} kullanımı yapılabilecek
    * -- Bazı fonksiyonlarda iyileştirmeler yapıldı.
    * -- İşi biten değişkenler Unset() edildi.
    * -- Fonksiyon Sonucunu Fonksiyon ismiyle çağırma özelliği eklendi ileri sürümlerde {$sonuc} kullanımı kaldırılacak. 
    * v1.1.1
    * ======  23.09.2009
    * -- Template ile Sütun Başlangıcı Fonksiyondan sonraya alındı (Artık Satırlar için de Fonksiyon kullanılabilecek Her Satır için sınıf değişkenleri ile oynanabilecek.)
    * -- OnlyRead propertyler düzenlendi.
    * -- Protected Fonksiyonlar Duzenlendi.
    * -- hatalar htmlspecialchars() fonksiyonundan geçirildi
    * v1.1.0
    * ======
    * -- totalTime() Fonksiyonu Eklendi . Bağlantıdan İtibaren geçen microsaniyelik zamanı yazar.
    * -- sqlCount Property Eklendi . Toplam Sorgu sayısını yazar.
    * -- debug Mode Eklendi.  debug='ON' durumunda her Sorgudan Sonra Toplam Microsaniyeyi etkilenen satır sayısını ve Sorguyu gosterir.
    * v1.0.9
    * ======
    * -- query() fonksiyonu eklendi. Artık sınıf olarak dönüyor. $db->query()->say()  $db->query()->grid();  gibi kullanılabilecek
    * -- Baglan() Fonksiyonuna return link Eklendi. İkinci Sınıf Oluşturulmadan Yeni Bir Bağlantı yapılabilecek
    * -- Satır Sonu unutulan </tr> eklendi.
    * v1.0.8
    * =======
    * -- ConClone() Fonksiyonu Eklendi. var Olan bir Sınıftan Aynı bağlantı Değerlerinde başka bir sınıf turetmenize yarar.(İç İçe Gridlerde Aynı Sınıf Sonsuz Döngüye Neden Oluyordu.)
    * v1.0.7
    * =======
    * -- baslik_ozellikleri() Fonksiyonu Eklendi (Sütün Başlıklarına Ek özellikler verilebilecek)
    * -- insertten sonraki son autoincreament değerini alabilmek için sonid() fonksiyonu yazıldı
    * -- eko() Fonksiyonu değiştirildi ilk sutünun artık değeri olarak dönüyor
    * v.1.0.6
    * =======
    * -- Gridte sonuç bulunamayınca yapılan tag eksikliği giderildi.
    * -- Link Kontrolu kaldırıldı. Default $this->link kullanıldı
    * -- Diğer Gereksiz if kontrollerinden arındırıldı. Stabilizeyşın :)
    * v1.0.5
    * ======
    * -- Update_Array Fonksiyonu Yazıldı (insert_array) ile aynı mantıkta kolaylık sağlıyor.
    * -- Joker Fonksiyon Eko() Eklendi (: 
    * v1.0.4
    * ======
    * -- Ard arda Oluşturulan Gridlerin Birleştirilmesindeki Sorun Giderildi.
    * -- Başlıklarda TH yerine TD  kullanıldı.
    * v1.0.3
    * ======
    * -- Şartlı Template güçlendirildi  artık dahil ettiğiniz fonksiyonun sonucunu da templatte {$sonuc}  olarak kullanabilirsiniz.
    * -- Insert array Fonksiyonundaki Hata Düzeltildi (Değer Yerine de Sütun Adını Atıyordu.)
    * -- Gridden Sonraki Getir() sorunu giderildi (data_seek).
    * -- Otomatik Hata Gösterim Ayarı Eklendi $db->hata_goster
    * v1.0.2
    * ======
    * -- Dar Gelir Tufana dar Gelir (: 22"  bile dar gelir :P
    * -- Sutun_Templatei icad etmem guzel oldu :P
    * -- Sutuna template Mantığında değişkenlik ve düzenlenebilirliğin yanınnda şartlı template uygulaması da yaptım kikiki (:
    * -- Dışardan Tanımladığınız bir Fonksiyonu Gride Dahil edip her satır için ayrı çalıştırabilirsiniz.
    * -- pek kullanışlı olmasa bile tablo ozellikleri ve stil eklendi.
    * -- array insert fonksiyonu da eklendi daha kolay ve hatasız insert sorguları yapabilirsiniz.(tek satır tabi (:)
    * -- Sütun Pasif Edebilme Birden fazla gridi aynı Data Source ile ekrana basabilme eklendi.
    * -- Sütun Başlıkları Büyük Eksiklikti o da eklendi (: Sutun başlıklarınız bir dizi vererek değiştirebilirsiniz
    * -- Bunlarla yetinmiyosanız aferin yetinmeyin zaten ben de boyle bırakacak değilim devamı gelecek.
    * v1.0.1
    * ======
    * -- Grid Fonksiyonu eklendi.
    * -- Grid bu kadar basit bırakılamazdı Sutun_linkleme özelliği eklendi listeleme işlemleri daha kolay oldu.
    * v1.0
    * ======
    * -- Hemen hemen her programlamada ihtiyacımız olan tabloları eziyet olmaktan çıkarmaya karar verdik vesselam..
    * -- Multi-Connect . Query. Fetch . Error  gibi mysql in olmazlarını toplayıp bir sınıf yaptık.
    * */
    class D3Sql{

        var $sonhata,$sonsql,$sonquery,$tablo_baslik,$grid_footer;
        var $aktif_sutunlar               =array();
        var $sutun_adlari                 =array();
        var $tum_hatalar                  =array(); 
        var $style                        =array(
            "thead" =>  "thead",
            "row1"  =>  "row1",
            "row2"  =>  "row2",
        );
        var $tablo_ozellikleri            = array(
            "class" =>  "sortable",
            "id"    =>  "sortable_tablo"
        );
        var $hata_goster                  = True;
        var $debug                        = 'OFF'; 
        protected $dbhost,$dbuser,$dbpass,$dbname,$link,$sqlCount=0,$mTime;
        protected $baslik_ozellikleri     = array();
        protected $sutun_templates        = array();
        protected $plugins                = array();
        private $hata_charset             = 'UTF-8';

        /**
        * Veritabanı Bağlantı Fonksiyonu
        * 
        * @param mixed $dbhost Veritabanı Sunucu Adresi
        * @param mixed $dbuser Veritabanı Kullanıcı Adı
        * @param mixed $dbpass Veritabanı Şifresi
        */
        function baglan($dbhost,$dbuser,$dbpass) 
        {
            $mictime=explode(' ',microtime());
            $this->mTime=(double)$mictime[0]+(double)$mictime[1];
            $this->dbhost = $dbhost;
            $this->dbuser = $dbuser;
            $this->dbpass = $dbpass;

            return  $this->link = @mysql_connect($this->dbhost,$this->dbuser,$this->dbpass) or $this->hata($this->dbhost.' Sunucusuna Bağlanırken Hata Oluştu <hr>'.$this->mysql_hata());
        }

        /**
        * VeriTabanı Seçme Fonksiyonu
        * 
        * @param mixed $db İşlem Yapmak istediğiniz Veritabanı Adı
        */

        function dbsec($db)
        {
            $db = $this->pluging_yeri('before_dbsec',$db);
            $this->dbname = (string)$db;
            @mysql_select_db($this->dbname,$this->link);
            $this->pluging_yeri('after_dbsec');
            return $this;

        }
        /**
        * Aynı bağlantıyı Tekrar Sağlayarak Yeni Sınıf Oluşturmanıza Yarar. | v1.0.8
        * 
        * @param mixed $Class
        */
        function ConClone($Class){
            $this->pluging_yeri('before_conclone');
            $this->baglan($Class->dbhost,$Class->dbuser,$Class->dbpass);
            $this->dbsec($Class->dbname); 
            $this->pluging_yeri('after_conclone');  
        }
        /**
        * Execute Fonksiyonu
        * 
        * @param mixed $sql Sql Cümlesi
        * @return resource
        */
        function sql($sql) {

            $this->aktif_sutunlar=array();
            $this->sutun_templates=array();

            $this->sonsql=(string)$sql=$this->pluging_yeri('before_sql',$sql);
            $query=@mysql_query($this->sonsql,$this->link) OR $this->hata($this->sonsql.'  Cümlesi Sorgulanırken Hata Oluştu<hr>'.$this->mysql_hata($this->mysql_hata()));
            $this->sqlCount++;
            if ($this->debug=='ON') {
                $this->pluging_yeri('debug_insql');
                echo '<span class="olumsuz" onmouseover="overlib(\'<div class=olumlu>'.str_replace("'","\\'",$sql).'</div>\');" onmouseout="nd();">Sorgu '.$this->sqlCount.' Toplam : '.$this->totalTime().' Saniye'.($this->etkilenen()>0 ? ' Etkilenen Satir : '.$this->etkilenen() : null).'</span><br>';
            }
            return $this->sonquery=$query;
        }

        /**
        * Sınıf Olarak Dönen Execute Fonksiyonu (v1.0.9)
        * 
        * @param mixed $sql Sql Cümlesi
        * @return class
        */
        function query($sql) {
            $this->sql($sql);
            return $this;
        }
        /**
        *  Mysql_Fetch_Assoc
        *  @return array
        */
        function getir(){
            $row =  @mysql_fetch_assoc(func_num_args()>0 ? func_get_arg(0):$this->sonquery);  
            //TODO : uyarı!! bu tüm sorguların tüm satırlarında çalışacağı için gereksiz bir  döngü olacaktır! ilk fırsatta tüm tarih formatları düzeltilip buradan kaldırılmalı
            if($row)
            {
                foreach($row as &$data)
                {
                    if(preg_match('/^\d{4}-\d\d-\d\d(?P<saat> \d\d:\d\d:\d\d)?$/',$data = trim($data),$matches))
                    {
                        if(isset($matches['saat']))
                            $data = date('d.m.Y H:i:s',strtotime($data));
                        else
                        {
                            $data = date('d.m.Y',strtotime($data));
                        }
                    }
                }
            }

            return $row;
        }

        function fetch_all($sql,$filter = null)
        {
            $rows = array();
            if($query = $this->sql($sql))
            {
                while($row = $this->getir($query))
                {
                    if($filter !== null && is_callable($filter))
                        $filter($row);
                    $rows[] = $row;
                }
            }
            return $rows;
        }

        /**
        *  Mysql_Fetch_Row
        *  @return array
        */
        function rowgetir(){
            return @mysql_fetch_row(func_num_args()>0 ? func_get_arg(0):$this->sonquery);   
        }

        /**
        * İstediğiniz Sütun için Şablon mantığı ile şekil vereiblirsiniz.
        * 
        * @param mixed $sutun_adi Uygulamak istediğiniz Sütun
        * @param mixed $template  Sütuna Uygulamak istediğiniz şablon
        * @param mixed $degisecek_sutunlar
        */
        function sutun_template($sutun_adi,$template,$degisecek_sutunlar=NULL) {
            $this->sutun_templates[$sutun_adi]= func_num_args()>3 ? array($template,$degisecek_sutunlar,func_get_arg(3)):array($template,$degisecek_sutunlar);
        }
        /**
        * Sütün Başlıkları için En Özellikler
        * 
        * @param mixed $sutun_adi  Etkilenmesini İstediğiniz Başlık Sütünunun Adı
        * @param mixed $ozellik_dizisi özellik dizisi
        */

        function baslik_ozellikleri($sutun_adi,$ozellik_dizisi){
            $this->baslik_ozellikleri[$sutun_adi]=$ozellik_dizisi;
        }
        /**
        * En Son Sorguladığınız Cümleyi tanımladığınız şablonlara göre Tablo haline getirir.
        * @return sring
        */          
        function grid()
        {
            $sinirli = count($this->aktif_sutunlar)>0;
            foreach ($this->tablo_ozellikleri AS $anahtar=>$deger) 
            {
                $tablo_ozellikleri .=' '.$anahtar.'="'.$deger.'"';
            }

            $this->grid=$this->pluging_yeri('before_grid',''); 
            $this->grid.='<table'.$tablo_ozellikleri.'>'."\n".$this->tablo_baslik."\n"; 

            $resource=func_num_args()>0 ? func_get_arg(0) :$this->sonquery;

            if (!is_resource($resource) OR get_resource_type($resource)!="mysql result") {
                $this->hata('Gride Dökmek İstediğiniz Değişken Bir mysql datasource değil.'); 
            }else {
                if ($this->say()<1) {
                    $this->pluging_yeri('on_norows');
                    $this->grid.='<tr><td class="sonuc_yok">Sonuç Yok.!</td></tr>';
                } else {

                    $this->jump(0,$resource);

                    $baslik=$this->getir($resource);
                    $this->grid.='<tr class="'.$this->style['thead'].'">';
                    foreach ($baslik AS $sutun_adi=>$data) {


                        if (!$sinirli OR (in_array($sutun_adi,$this->aktif_sutunlar))) {
                            if (in_array($sutun_adi,array_keys($this->baslik_ozellikleri))) {

                                foreach ($this->baslik_ozellikleri[$sutun_adi] AS $ozellik_adi=>$ozellik_degeri){
                                    $baslik_ozellikleri[$sutun_adi].=" $ozellik_adi=\"$ozellik_degeri\"";   
                                }
                                unset($ozellik_adi,$ozellik_degeri);

                            }
                            $this->grid.='<td'.$baslik_ozellikleri[$sutun_adi].'>';
                            array_key_exists($sutun_adi,$this->sutun_adlari) ? $sutun_adi=$this->sutun_adlari[$sutun_adi] : $sutun_adi=$sutun_adi;
                            $this->grid.=$this->pluging_yeri('sutun_adi',$sutun_adi);  
                            $this->grid.='</td>';
                            unset($sutun_adi);

                        }

                    }
                    $this->grid.='</tr>'."\n";
                    $this->jump(0,$resource);
                    while ($data=$this->getir($resource)) {
                        unset($sutunlar);  
                        foreach ($data As $sutun=>$icerik) {
                            $this->grid_sutun=$data;
                            if (array_key_exists($sutun,$this->sutun_templates)) {
                                $gridtemp=$this->sutun_templates[$sutun];   
                                $kullanilan_func_sonucu=@call_user_func($gridtemp[2],$data);// or $this->hata($gridtemp[2].' Adlı Fonksiyonunuzda Bir Sorun Var ..! Bir Değer Döndürmuyo Olabilir  Bkz. Return: ');

                                if (count($gridtemp)==2 OR $kullanilan_func_sonucu){

                                    $tmp=$gridtemp[0];
                                    $tmp=str_replace('{$sonuc}',$kullanilan_func_sonucu,$tmp);

                                    if (is_array($gridtemp[1])) {
                                        foreach ($gridtemp[1] AS $num=>$sutun_name) {

                                            $tmp=str_replace('{$'.($num+1).'}',$data[$sutun_name],$tmp);
                                            $tmp=str_replace('{$'.$sutun_name.'}',$data[$sutun_name],$tmp);
                                        }

                                    }else {
                                        $tmp=str_replace('{$1}',$data[$gridtemp[1]],$tmp);   
                                        $tmp=str_replace('{$'.$gridtemp[1].'}',$data[$gridtemp[1]],$tmp); 

                                        foreach ($data AS $sutun_adi=>$sutun_degeri) {
                                            $tmp=str_replace('{$'.($sutun_adi).'}',$this->grid_sutun[$sutun_adi],$tmp);   
                                        }

                                    }

                                    $icerik=$tmp;

                                } 
                            }

                            if (!$sinirli OR in_array($sutun,$this->aktif_sutunlar)) {    

                                $sutunlar.='<td>';  
                                $sutunlar.=$icerik;  
                                $sutunlar.='</td>';  

                            }   

                        }

                        $this->grid.='<tr class="'.$this->style['row1'].'" onmouseover="this.className=\''.$this->style['row2'].'\'" onmouseout="this.className=\''.$this->style['row1'].'\'">';
                        $this->grid.=$sutunlar; unset($sutunlar);
                        $this->grid.='</tr>'."\n";  
                    }

                }
            }
            $this->grid.=$this->grid_footer."\n";
            $this->grid.='</table>'."\n";
            $this->jump(0,$resource);
            return  $this->pluging_yeri('after_grid',$this->grid);
        }
        /**
        * Ek olarak sınıfta çalıştırmak istediklerinizi plugin mantığı ile yerini yazarak çalıştırabilirsiniz.
        * 
        * @param mixed $plugin_yeri
        * @param mixed $function_adi
        */
        function plugin_ekle($plugin_yeri,$function_adi){
            $this->plugins[$plugin_yeri][]=$function_adi;
            return $this;
        }
        /**
        * Sınıf İçinde Plugin Çalıştırmaya Yarar.
        * @param mixed $plugin_yeri
        */
        protected function pluging_yeri($plugin_yeri,$Etkilenecek=NULL){
            if(in_array($plugin_yeri,$this->plugins)){
                if(count($this->plugins[$plugin_yeri])>0){
                    foreach($this->plugins[$plugin_yeri] As $FuncName){
                        $Etkilenecek=@call_user_func($FuncName,$Etkilenecek);
                    }
                }
            }
            return $Etkilenecek;  
        }
        /**
        * Mysql Fetch Object Methodu ile Datasetten Objeler Döner
        * @return Array 
        */
        function obje_getir(){
            return @mysql_fetch_object(func_num_args()>0 ? func_get_arg(0):$this->sonquery); 
        }
        /**
        * Kaçış karakterlerinden arındırma fonksiyonu
        * 
        * @param mixed $string
        * @return string
        */
        function escape($string){
            if (is_array($string)){

                foreach ($string as $anum=>$adata) {

                    $escaped[$anum]=@mysql_real_escape_string($adata);
                }   

            }
            else {

                $escaped=@mysql_real_escape_string($string);
            }

            return $escaped;

        }
        /**
        * Mysql_NumRows Metodu
        * @return int
        */
        function say($query = NuLL) {
            if($query)
            {             
                return @mysql_numrows($query);
            }
            else
            {
                return @mysql_numrows($this->sonquery);
            }

        }
        /**
        * Select Yaparken eko adını verdiğiniz sutünun değerini yazar
        * Örnek : Select adi eko from isimler where id='1'
        * 
        * @param resource $sql
        */
        function eko($sql){
            $sql=$this->sql($sql);
            $row=$this->rowgetir();
            return $row[0];
        }
        /**
        * Insert into işlemini Kolay ve hatasız yapabilmek için.
        * 
        * @param mixed $tablo  Tablo Adı
        * @param mixed $dizi   Insert Dizisi
        * @return resource     Dataset
        */
        function insert_array($tablo,$dizi) {

            $sutunlar=array_keys($this->escape($dizi));
            $degerleri=array_values($this->escape($dizi));
            $sutun=implode(',',$sutunlar);

            //buna bir çözüm bu tufy!
            foreach($degerleri as &$d)
            {
                if($d != 'NOW()')
                {
                    $d = "'{$d}'";
                }
            }

            $deger=implode(',',$degerleri);


            return  $this->sql('INSERT INTO '.$tablo.' ('.$sutun.') VALUES ('.$deger.')');

        }
        /**
        * Update işlemini Kolay ve hatasız yapabilmek için.
        * 
        * @param mixed $tablo Tablo adı
        * @param mixed $dizi  Update Dizisi
        * @param mixed $Where Varsa şart
        * @return resource
        */
        function update_array($tablo,$dizi,$Where=False){

            foreach ($dizi As $Field=>$Data){
                $Update .=$Field."='".$Data."'";
            }

            $UpdateSql="UPDATE ".$tablo." SET ".$Update;

            if ($Where){
                $UpdateSql .=" WHERE ".$Where;  
            }

            return $this->sql($UpdateSql);

        }
        /**
        * Son Insert Sorgusundan Sonraki AutoIncreament Değeri
        * @return int
        */
        function sonid(){
            return @mysql_insert_id($this->link);
        }
        /**
        * 
        */
        function Free(){
            @mysql_free_result(func_num_args()>0 ? func_get_arg(0):$this->sonquery);
            return $this;
        }
        /**
        * Mysql bağlantısını kapatır
        * @return Boolean
        */
        function kop() {
            return @mysql_close($this->link);
        }
        /**
        * Mysql Hatası Olarak Döner
        * @return String
        */
        function mysql_hata() {
            return @mysql_error($this->link).' Hata No : '.$this->hata_no(); 

        }  
        /**
        * En Son Alınan Mysql hata numarası.
        * @return ErrCode
        */
        function hata_no(){
            return @mysql_errno($this->link);

        }
        /**
        * Ekrana Basılan hataların karaktersetini Duzenler
        * 
        * @param mixed $charset
        */
        function hata_charset($charset) {
            $charset ? $this->hata_charset=$charset :  $this->hata_charset;
            return $this;
        }

        /**
        * mysql_data_seek görevi görür datasourceda gitmek istediğiniz satıra numarsıyla ulaşabiliriz.
        * 
        * @param mixed $Rownum
        */
        function jump($Rownum,$Resource=False){
            @mysql_data_seek($Resource?$Resource:$this->sonquery,$Rownum);
            return $this;
        }
        /**
        * Sorgudan Dönen ya da Etkilenen Satır Sayısı Döndürür
        *  @return int
        */
        function etkilenen(){
            return @mysql_affected_rows($this->link);
        }
        /**
        * Hata Ekler
        * 
        * @param mixed $hatametni
        */
        protected function hata($hatametni){


            // $this->sonhata = '<div style="background:#ffcccc;color:#d00000;border:1px solid;font-weight: 700;padding:10px;font-size:13px;text-align:Center;">'.str_replace('HRR','<hr>',htmlspecialchars(str_replace('<hr>','HRR',$hatametni))).'<br><center>Yardım İçin : <a href="index.php?p=yardim">Tıklayın</a></center></div>';
            $back = debug_backtrace();
            $this->sonhata = 
            '<div style="background:#ffcccc;position:absoulte;padding:5px">
            <pre>' . $hatametni .'
            ' . $back[1]['file'] . ' on line ' . $back[1]['line'] . '
            </pre>
            </div>';

            if (function_exists('iconv')) 
                $this->sonhata = iconv('UTF-8',$this->hata_charset,$this->sonhata);

            $this->tum_hatalar[] = $this->sonhata;

            if ($this->hata_goster)
                echo $this->sonhata;

        }
        /**
        * Nesne Oluşturulduğu Andan itibaren geçen zamanı saniye cinsinden verir X.XX
        * @return float
        */
        function totalTime()
        {
            $micTime = explode(' ',microtime());
            $endTime = (double)$micTime[0]+(double)$micTime[1];
            return round($endTime-$this->mTime,3);
        }
        /**
        * Nesne Oluşturulduğu andan itibaren yapılan sorgulama sayısı olarak döner
        * @return integer
        */
        function sqlCount()
        {
            return $this->sqlCount;
        }   

    }
?>